package paper.cluster;

import java.sql.*;

import java.io.PrintWriter;
import java.io.FileWriter;
import java.io.IOException;

import java.util.HashSet;
import java.util.HashMap;
import java.util.Date;
import java.util.Random;
import java.util.Iterator;
import java.util.Vector;

import paper.db.DB;
import paper.db.Paper;
import paper.db.PaperCache;

class Matrix
{
    final static int BIG = 1000000;
    int[][] cnts;
    int rows, cols;
    Matrix(int r, int c)
    {
        cnts = new int[r][c];
        rows = r;
        cols = c;
    }

    Matrix( Matrix c )
    {
        rows = c.rows;
        cols = c.cols;
        cnts = new int[rows][cols]; 
        for(int i=0; i<rows; i++)
            for( int j=0; j<cols; j++)
                cnts[i][j] = c.cnts[i][j];
    }

    void clear(int x)
    {
        for(int i=0; i<rows; i++)
        {
            for(int j=0; j<cols; j++)
                cnts[i][j] = x;
        }
    }

    void dump()
    {
        for(int i=0; i<rows; i++)
        {
            for(int j=0; j<rows; j++)
                System.out.print( cnts[i][j] + " " );
            System.out.println("");
        }
    }

    int min(int a, int b)
    {
        if( a<b )
            return a;
        return b;
    }

    void multiply( Matrix other )
    {
        Matrix copy = new Matrix(this);
        for(int i=0; i<rows; i++)
        {
            for( int j=0; j<cols; j++)
            {
                int x = BIG;
                for( int k=0; k<rows; k++)  
                {
                    int res;
                    if( copy.cnts[i][k] == BIG || other.cnts[k][j] == BIG)
                        res = BIG;
                    else
                        res = copy.cnts[i][k] + other.cnts[k][j];
                    x = min(x,res);
                }
                cnts[i][j] = x;
            }
        }
    }

}

public class GenMatrices 
{
    static public Matrix makeDistanceMatrix(HashSet<Paper> x)
    {
        // A flat (ie indexed) array of papers
        Paper[] flat = new Paper[ x.size() ];
        int i=0;
        for(Iterator<Paper> j = x.iterator(); j.hasNext(); )
            flat[i++] = j.next();

/*        // Using a map to turn a reference into an index
        HashMap<Paper,Integer> lookup = new HashMap<Paper,Integer>();
        for(i=0; i<x.size(); i++)
            lookup.put(flat[i],i);
*/
        Matrix adj = new Matrix( x.size(), x.size() );
        for(i=0; i<x.size(); i++)
        {
            for(int j=0; j<x.size(); j++)
            {
                if( i==j )
                    adj.cnts[i][j] = 0;
                else
                {
                    HashSet<String> auth = new HashSet<String>(flat[i].canonAuthors);
                    auth.retainAll( flat[j].canonAuthors );
                    if( auth.size() > 0 )
                        adj.cnts[i][j] = 1;
                    else
                        adj.cnts[i][j] = Matrix.BIG;
                }
            }
        }
        Matrix m = new Matrix( x.size(), x.size() );
        for(i=0; i<x.size(); i++)
        {
            for( int j=0; j<x.size(); j++)
            {   
                if( i==j )
                    m.cnts[i][j] = 0;
                else
                    m.cnts[i][j] = Matrix.BIG;
            }
        }
        for(i=0; i<10; i++)
            m.multiply(adj);
        int counts[] = new int[10];
        for(i=0; i<x.size(); i++)
            for(int j=0; j<x.size(); j++)
                if( m.cnts[i][j] < 10)
                    counts[ m.cnts[i][j] ]++;
        for(i=0;i<10;i++)
            System.out.println(counts[i]);
        
        return m;
    }
        

    static public void makeBiCoauthor(PrintWriter out, HashSet<Paper> x) throws IOException
    {
        HashSet<String> allAuthors = new HashSet<String>();
        for(Iterator<Paper> i=x.iterator(); i.hasNext(); )
        {
            Paper p = i.next();
            allAuthors.addAll( p.canonAuthors );
        }
        out.println("authors = {");
        for(Iterator<String> i=allAuthors.iterator(); i.hasNext(); )
        {
            String name = i.next();
            out.println("'"+name+"';");
        }
        out.println("}");
        out.println("papers = {");
        for(Iterator<Paper> i=x.iterator(); i.hasNext(); )
        {
            Paper p = i.next();
            String tit = p.title.replace('\'',' ').replace('\n',' ');
            out.println("'"+tit+"';");
        }
        out.println("}");
    
        out.println("cspubs = [");
        for(Iterator<Paper> i=x.iterator(); i.hasNext(); )
        {
            Paper row = i.next();
            for(Iterator<String> j=allAuthors.iterator(); j.hasNext(); )
            {
                String name = j.next();
                if( row.canonAuthors.contains(name) )
                    out.print("1 ");
                else
                    out.print("0 ");
            }
            out.println(";");
        }
        out.println("];");
    }

    static public void makeCoauthor(PrintWriter out,HashSet<Paper> x) throws IOException
    {
        out.println("cspubs = [");
        for(Iterator<Paper> i=x.iterator(); i.hasNext(); )
        {
            Paper row = i.next();
            for(Iterator<Paper> j=x.iterator(); j.hasNext(); )
            {
                Paper col = j.next();
                HashSet<String> cp = new HashSet<String>(row.canonAuthors);
                cp.retainAll( col.canonAuthors );
                if( cp.size() > 0 )
                    out.print("1 ");
                else
                    out.print("0 ");
            }
            out.println(";");
        }
        out.println("];");
    }

    static public void makeCoauthorDiff(PrintWriter out,HashSet<Paper> x) throws IOException
    {
        out.println("cspubs = [");
        for(Iterator<Paper> i=x.iterator(); i.hasNext(); )
        {
            Paper row = i.next();
            for(Iterator<Paper> j=x.iterator(); j.hasNext(); )
            {
                Paper col = j.next();
                HashSet<String> cp = new HashSet<String>(row.canonAuthors);
                cp.retainAll( col.canonAuthors );
                int iSize = cp.size();
                cp.addAll(row.canonAuthors); 
                cp.addAll(col.canonAuthors); 
                int uSize = cp.size();
                double diff = 1.0 - (double)iSize / (double)uSize;
                out.print(diff + " ");
            }
            out.println(";");
        }
        out.println("];");
    }
    public static void main(String[] args) throws IOException
    {
        String filter = "xx.zip";
        for(int i=0; i<args.length; i++)
            if( args[i].substring(0,2).equals("-f") )
                filter = args[i].substring(2);
        PaperCache cache = new PaperCache();
        HashSet<Paper> x = Paper.loadUrlSet(filter,cache);

        Matrix dist = makeDistanceMatrix(x);
/*
        PrintWriter out = new PrintWriter(new FileWriter( "bicoauth-pxa.mat" ));
        GenMatrices.makeBiCoauthor(out,x);
        out.close();

        out = new PrintWriter(new FileWriter( "coauth-pxp.mat" ));
        GenMatrices.makeCoauthor(out,x);
        out.close();

        out = new PrintWriter(new FileWriter( "coauth-diff-pxp.mat" ));
        GenMatrices.makeCoauthorDiff(out,x);
        out.close();
*/
    }
}

